package sessions;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.ejb.Stateless;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import sessions.abilitiesSession.AbilitySessionRemote;
import sessions.friendshipSession.FriendshipSessionRemote;
import sessions.helpSession.HelpRequestsessionRemote;
import sessions.requestAbilitySession.RequestAbilitySessionRemote;
import sessions.requestFriendshipSession.FriendshipRequestSessionRemote;

import entities.Utente;

@Stateless
public class LoginSystem implements LoginSystemRemote, LoginSystemLocal {

	@PersistenceContext(unitName = "MPHProject")
	private EntityManager manager;

	public LoginSystem() {
	}

	public int insertUser(String email, String nome, String cognome,
			String password, String data, String numTelefono,
			String NumCellulare) {
		try {

			Date utilDate = null;
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
			utilDate = formatter.parse(data);

			Utente user = new Utente();
			user.setEmail(email);
			user.setNome(nome);
			user.setCognome(cognome);
			user.setPassword(password);
			user.setTipoUtente("utente");
			user.setDataNascita(utilDate);
			user.setNumTelefono(numTelefono);
			user.setNumCellulare(NumCellulare);

			manager.persist(user);

			return user.getId();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return 0;
	}

	public Utente getUtente(String email, String password) {
		try {
			Query q = manager
					.createQuery("FROM Utente u WHERE u.email=:email AND u.password =:password");
			q.setParameter("email", email);
			q.setParameter("password", password);
			return (Utente) q.getSingleResult();
		} catch (Exception exc) {
		}
		return null;
	}

	/**
	 * restituisce l'utente associato all'id passato
	 * 
	 * @param id
	 *            id utente da ricercare
	 * @return l'utente con l'id associato
	 */
	public Utente getUserByID(int id) {
		try {
			Query q = manager.createQuery("FROM Utente u WHERE u.id=:id");
			q.setParameter("id", id);
			return (Utente) q.getSingleResult();
		} catch (Exception exc) {

		}
		return null;
	}

	/**
	 * ritorna tutti gli utenti cercati per nome e/o cognome
	 * 
	 * @param name
	 *            il nome dell'utente da cercare
	 * @param surname
	 *            il cognome dell'utente da cercare
	 * @return la lista degli utenti trovati
	 */
	public ArrayList<Utente> getUsers(String name, String surname) {
		Query q;
		if (surname == null) {
			// ricerco solo il nome
			q = manager.createQuery("FROM Utente u WHERE u.nome=:name");
			q.setParameter("name", name);
		} else {
			if (name == null) {
				// ricerco solo il cognome
				q = manager
						.createQuery("FROM Utente u WHERE u.cognome=:surname ");
				q.setParameter("surname", surname);
			} else {
				// ricerco entrambi
				q = manager
						.createQuery("FROM Utente u WHERE u.nome=:name AND u.cognome=:surname ");
				q.setParameter("name", name);
				q.setParameter("surname", surname);
			}
		}
		try {
			return (ArrayList<Utente>) q.getResultList();
		} catch (Exception exc) {
			System.out.print("Errore nella query ricerca utente");
		}
		return null;
	}

	/**
	 * restituisce gli utenti con una determinata abilitˆ
	 * 
	 * @param idAbility
	 *            l'abilitˆ da ricercare
	 * @return la lista di utenti che sanno svolgere l'attivitˆ
	 */
	public ArrayList<Utente> getUsersForAbility(int idAbility) {
		Query q;
		q = manager
				.createNativeQuery(
						"SELECT * FROM Utente AS u1 WHERE u1.id IN "
								+ "(SELECT p.idu FROM Possiede AS p WHERE p.ida =:idAbility)",
						Utente.class);
		q.setParameter("idAbility", idAbility);
		try {
			return (ArrayList<Utente>) q.getResultList();
		} catch (Exception exc) {
			System.out.print("Errore nella query ricerca utente");
		}
		return null;
	}

	/**
	 * ritorna tutti gli utenti del DB
	 * 
	 * @return la lista di tutti gli utenti
	 */
	public ArrayList<Utente> getAllUsers() {
		Query q;
		q = manager.createQuery("FROM Utente");
		try {
			return (ArrayList<Utente>) q.getResultList();
		} catch (Exception exc) {
			System.out.print("Errore nella query ricerca utente");
		}
		return null;
	}

	/**
	 * elimina l'utente associato all'id passato
	 * 
	 * @param id
	 *            id utente da eliminare
	 * @return true se l'utente � stato eliminato correttamente, false
	 *         altrimenti
	 */
	public boolean eraseUser(int id) {

		try {
			Context jndiCtx = new InitialContext();
			// elimino tutte le richieste di amicizia
			FriendshipRequestSessionRemote friendshipRequestRemote = (FriendshipRequestSessionRemote) jndiCtx
					.lookup("Progetto/FriendshipRequestSession/remote");
			if (!friendshipRequestRemote.eraseUserRequest(id))
				return false;
			// elimino tutte le amicizie
			FriendshipSessionRemote friendshipSession = (FriendshipSessionRemote) jndiCtx
					.lookup("Progetto/FriendshipSession/remote");
			if (!friendshipSession.eraseUserFriendships(id))
				return false;
			// elimino tutte le richieste di abilita
			RequestAbilitySessionRemote abilityRequestSession = (RequestAbilitySessionRemote) jndiCtx
					.lookup("Progetto/RequestAbilitySession/remote");
			if (!abilityRequestSession.eraseUserAbilitiesRequest(id))
				return false;
			// elimino tutte le abilita
			AbilitySessionRemote abilitySession = (AbilitySessionRemote) jndiCtx
					.lookup("Progetto/AbilitySession/remote");
			if (!abilitySession.eraseUserAbilities(id))
				return false;
			// elimino feedback e le richieste di aiuto
			HelpRequestsessionRemote hrs = (HelpRequestsessionRemote) jndiCtx
					.lookup("Progetto/HelpRequestsession/remote");
			if (!hrs.eraseUserFeedbackandHelp(id))
				return false;
			manager.remove(getUserByID(id));
			if (getUserByID(id) == null)
				return true;
		} catch (Exception exc) {
			System.out.println("Errore nella query ricerca utente");
		}
		return false;
	}

	/**
	 * restituisce il tipo dell'utente che si è loggato null se l'utente o la
	 * password non esistono
	 * 
	 * @param id
	 *            Identificativo dell'utente
	 * @param password
	 *            Password associata all'identificativo
	 * @return Tipo
	 */
	public String getLoginType(int id, String password) {

		Utente user = manager.find(Utente.class, id);

		if (user == null)
			return null;

		if (user.getPassword().equals(password))
			return user.getTipoUtente();

		return null;
	}

}
